package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/google/uuid"
	"github.com/wailsapp/wails/v2/pkg/runtime"
)

type CleanTaskInfo struct {
	EventName string `json:"eventName"`
	Running   bool   `json:"running"`
	Total     int    `json:"total"`
	Handled   int    `json:"handled"`
}

type CleanLock struct {
	lock sync.Mutex
	CleanTaskInfo
}

func (c *CleanLock) TryLock() (string, bool) {
	if !c.lock.TryLock() {
		return "", false
	}

	c.Running = true
	c.EventName = fmt.Sprintf("clean_%s", uuid.NewString())
	return c.EventName, true
}

func (c *CleanLock) Release() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println(r)
		}
	}()

	c.lock.Unlock()
	c.Running = false
	c.EventName = ""
	c.Total = 0
	c.Handled = 0
}

var globalCleanLock = &CleanLock{}

func (a *App) CleanAttachment() (CleanTaskInfo, error) {
	return cleanAttachment(a.ctx)
}

func (a *App) GetCleanTask() CleanTaskInfo {
	return globalCleanLock.CleanTaskInfo
}

func cleanAttachment(ctx context.Context) (taskInfo CleanTaskInfo, err error) {
	eventName, locked := globalCleanLock.TryLock()
	if !locked {
		err = fmt.Errorf("clean task already in running")
		return
	}

	defer func() {
		r := recover()
		if err != nil || r != nil {
			globalCleanLock.Release()
		}
	}()

	realPath := GetAbsPath(globalConfig.AttachmentPath)
	files, err := os.ReadDir(realPath)
	if err != nil {
		return
	}

	count := 0
	for _, file := range files {
		if !file.IsDir() {
			count++
		}
	}
	globalCleanLock.Total = count

	go func() {
		defer func() {
			globalCleanLock.Release()
		}()

		// time.Sleep(10 * time.Second)
		handledCount := 0

		for _, file := range files {
			handledCount++

			time.Sleep(1 * time.Second)
			globalCleanLock.Handled = handledCount
			runtime.EventsEmit(ctx, eventName, handledCount)

			count := int64(0)
			err := db.Model(&Note{}).Where("content LIKE ?", "%"+file.Name()+"%").Count(&count).Error
			if err != nil {
				fmt.Println(err)
				continue
			}
			if count <= 0 {
				os.Remove(filepath.Join(realPath, file.Name()))
			}
		}

		runtime.EventsEmit(ctx, eventName, true)
	}()

	taskInfo = globalCleanLock.CleanTaskInfo
	return
}
